package com.dynamic.mybatis.core.session;

import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import com.dynamic.mybatis.core.datasource.DynamicDataSourceHolder;
import com.dynamic.mybatis.core.metadata.DynamicConfiguration;
import com.dynamic.mybatis.core.metadata.DynamicMappedStatement;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * @Description
 * @Author xs
 * @Date 2021/3/29 11:17
 */
public class DynamicSqlSessionTemplate {

    private DynamicSqlSession dynamicSqlSession;

    public DynamicSqlSessionTemplate(SqlSession sqlSession) {
        this.dynamicSqlSession = new DynamicSqlSession(sqlSession);
    }

    public SqlSession getSqlSession(){
        return dynamicSqlSession.getSqlSession();
    }

    public Connection getConnection(String mappedStatementId){
        Configuration configuration =   dynamicSqlSession.getSqlSession().getConfiguration();
        if(configuration == null || !(configuration instanceof DynamicConfiguration)){
           return dynamicSqlSession.getSqlSession().getConnection();
        }
        DataSource dataSource =   configuration.getEnvironment().getDataSource();
        if(!(dataSource instanceof AbstractRoutingDataSource)){
            return   dynamicSqlSession.getSqlSession().getConnection();
        }
        DynamicConfiguration dc = (DynamicConfiguration) configuration;
        DynamicMappedStatement dms = dc.getDynamicMappedStatement(mappedStatementId);
        if(dms == null){
          return   dynamicSqlSession.getSqlSession().getConnection();
        }
        Object datasourceKey;
        datasourceKey =  dms.getTargetDataSourceKey();
        if(datasourceKey == null ){
            if(ArrayUtils.isNotEmpty(dms.getDynamicDataSourceKeys())){
                datasourceKey =  dms.getDynamicDataSourceKeys()[0];
            }else {
                return   dynamicSqlSession.getSqlSession().getConnection();
            }
        }
        if(datasourceKey == null){
            return   dynamicSqlSession.getSqlSession().getConnection();
        }
        try {
            DynamicDataSourceHolder.set(datasourceKey);
           return dataSource.getConnection();
        } catch (SQLException e) {
           throw new RuntimeException(e);
        }finally {
            DynamicDataSourceHolder.clear();
        }
    }

    public DynamicSqlSession getDynamicSqlSession() {
        return dynamicSqlSession;
    }


    /**
     * @Description: 执行SQl并且执行后把动态sql从mybatis上下文中删除
     * @param dynamicMappedStatement sqlId
     * @param parameter 参数 一般使用Map
     * parameter.pagination = 1 分页查询
    　*/
    public  <T> T executeTest(DynamicMappedStatement dynamicMappedStatement, Object parameter) {
        return dynamicSqlSession.executeTest(dynamicMappedStatement, parameter);
    }


    /**
     * @Description: 执行SQl并把动态sql保存到mybatis上下文中
     * @param dynamicMappedStatement
     * @param parameter 参数 一般使用Map
     * parameter.pagination = 1 分页查询
    　*/
    public  <T> T  executeGenerator(DynamicMappedStatement dynamicMappedStatement,Object parameter){
        return dynamicSqlSession.executeGenerator(dynamicMappedStatement, parameter);
    }

    /**
     * @Description: 执行SQl
     * @param mappedStatementId sqlId
     * @param  parameter
     * parameter.pagination = 1 分页查询
     * @param dataSourceKey 数据源key
     */
    public  <T> T executeRouting(String mappedStatementId,Object parameter,Object dataSourceKey){
        return dynamicSqlSession.execute( mappedStatementId,dataSourceKey,parameter);
    }
    /**
     * @Description: 执行SQl
     * @param mappedStatementId sqlId
     */
    public  <T> T execute(String mappedStatementId){
        return dynamicSqlSession.execute(mappedStatementId);
    }

    /**
     * @Description: 执行SQl
     * @param mappedStatementId sqlId
     * @param parameter 参数 一般使用Map
     * parameter.pagination = 1 分页查询
     */
    public  <T> T execute(String mappedStatementId,Object parameter){
        return dynamicSqlSession.execute( mappedStatementId, parameter);
    }

    /**
     * @Description: 执行SQl
     * @param mappedStatementId sqlId
     * @param dataSourceKey 数据源key
     * @param parameter 参数 一般使用Map
     */
    public  <T> T execute(String mappedStatementId,Object dataSourceKey,Object parameter){
        return dynamicSqlSession.execute( mappedStatementId,dataSourceKey, parameter);
    }
}